using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace EuropeEngulfed.NET
{
    class ProductionMove : Move
    {
        //2.3 Strategic Warfare Building Limits
        private const int MAX_UBOATSPURCHASABLE = 8;
        private const int MAX_V1PURCHASABLE = 6;
        private const int MAX_V2PURCHASABLE = 2;
        public const int MAX_NUM_GERMAN_AIRCRAFT_POINTS = 4;
        private const int MAX_NUM_GERMAN_BOMBER_POINTS = 2;
        public const int MAX_NUM_BRITISH_AIRCRAFT_POINTS = 2;
        private const int MAX_NUM_BRITISH__BOMBER_POINTS = 1;
        public const int MAX_NUM_US_AIRCRAFT_POINTS = 6;
        private const int MAX_NUM_US_BOMBER_POINTS = 3;

        public const int AIRBORNE_STEP_COST = 2;
        public const int ARMOR_STEP_COST = 2;
        public const int CAVALRY_STEP_COST = 1;
        public const int ELITE_ARMOR_STEP_COST = 4;
        public const int ELITE_INFANTRY_STEP_COST = 2;
        public const int INFANTRY_STEP_COST = 1;
        public const int MILITIA_STEP_COST = 1;
        public const int FIELD_FORTIFICATION_COST = 5;
        public const int HEAVY_FIELD_FORTIFICATION_COST = 10;
        public const int GSU_COST = 5;

        public const int RUSSIAN_EMERGENCYCONSCRIPTION_TURN1 = 20;
        public const int RUSSIAN_EMERGENCYCONSCRIPTION_TURN2 = 15;
        public const int RUSSIAN_EMERGENCYCONSCRIPTION_TURN3 = 10;
        public const int RUSSIAN_EMERGENCYCONSCRIPTION_TURN4 = 5;

        public enum ProductionMoveType
        {
            blockReplacement,
            newBlock,
            russianEliteInfantryReinforcement,
            newGSU,
            newfleet,
            fighters,
            bombers,
            flak,
            uboats,
            ASW,
            V1,
            V2,
            specialAction,
            specialActionUnlimitedReplacement,
            fortification,
            sovietHeavyFortification,
        }
        private ProductionMoveType type;
        private MapInfo.CountryID country; //For Replacement or new units this is the actual country of the block or unit NOT the paying country
        private Block.BlockType blockType;
        private uint producedBlockMaxStrength; 
        private int previousBlockStrength;
        private int numBought;
        private MapInfo.RegionID region;
        private bool russianEmergencyConscription = false;
        private bool russianCadreBonus = false;
        private bool russianBritishProductionPenalty = false;

        public ProductionMoveType MoveType
        {
            get
            {
                return type;
            }
        }

        public bool RussianBritishProductionPenalty
        {
            get
            {
                return russianBritishProductionPenalty;
            }

            set
            {
                if(value)
                {
                    if (this.country != MapInfo.CountryID.USSR && country != MapInfo.CountryID.GreatBritain)
                        throw new InvalidOperationException("Penalty only possible for Russians and British");
                }
                russianBritishProductionPenalty = value;
            }
        }

        public bool RussianEmergencyConscription
        {
            get
            {
                return russianEmergencyConscription;
            }

            set
            {
                russianEmergencyConscription = value;
            }
        }

        public bool RussianCadreBonus
        {
            set
            {
                if(value)
                {
                    if (this.country != MapInfo.CountryID.USSR)
                        throw new InvalidOperationException("Cadre Bonus only possible for Russians");
                    if (this.type != ProductionMoveType.newBlock)
                        throw new InvalidOperationException("Cadre Bonus only possible for new blocks");
                }
                russianCadreBonus = value;
            }
        }

        public MapInfo.RegionID ProductionRegion
        {
            get
            {
                return region;
            }
        }

        public Block.BlockType ProductionBlockType
        {
            get
            {
                return blockType;
            }
        }

        public MapInfo.CountryID Country
        {
            get
            {
                return country;
            }
        }

        public int NumBought
        {
            get
            {
                return numBought;
            }
        }

        public uint MaxStrength
        {
            get
            {
                return producedBlockMaxStrength;
            }
        }

        public ProductionMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase,ProductionMoveType type, MapInfo.CountryID country,Block.BlockType blockType,
            int previousBlockStrength, int numBought, MapInfo.RegionID region, uint producedBlockMaxStrength)
            : base(gameDate, gamePhase, GameTurn.GameSubPhase.Production)
        {
            this.type = type;
            this.country = country;
            this.blockType = blockType;
            this.previousBlockStrength = previousBlockStrength;
            this.numBought = numBought;
            this.region = region;
            this.producedBlockMaxStrength = producedBlockMaxStrength;
        }

        public static ProductionMove CreateBlockReplacementMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase, MapInfo.CountryID country,
                                                                        Block.BlockType blockType, int previousBlockStrength, MapInfo.RegionID region, uint producedBlockMaxStrength)
        {
            return new ProductionMove(gameDate, gamePhase, ProductionMoveType.blockReplacement, country, blockType, previousBlockStrength, 1, region, producedBlockMaxStrength);
        }

        public static ProductionMove CreateNewBlockMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase, MapInfo.CountryID country, Block.BlockType blockType, MapInfo.RegionID region, uint producedBlockMaxStrength)
        {
            return new ProductionMove(gameDate, gamePhase, ProductionMoveType.newBlock, country, blockType, 0, 1, region, producedBlockMaxStrength);
        }

        public static ProductionMove CreateRussianEliteInfantryReinforcementMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase, MapInfo.RegionID region)
        {
            return new ProductionMove(gameDate, gamePhase, ProductionMoveType.russianEliteInfantryReinforcement, MapInfo.CountryID.USSR, Block.BlockType.eliteInfantry, 0, 1, region, 4);
        }

        public static ProductionMove CreateNewFleetMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase, MapInfo.CountryID country, MapInfo.RegionID homeSeaRegion)
        {
            return new ProductionMove(gameDate, gamePhase, ProductionMoveType.newfleet, country, Block.BlockType.airborne, 0, 1, homeSeaRegion, 0);
        }

        public static ProductionMove CreateStratWarfarePurchaseMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase, MapInfo.CountryID country, ProductionMoveType stratAssetType, int numBought)
        {
            if(stratAssetType != ProductionMoveType.ASW && stratAssetType != ProductionMoveType.bombers &&
                stratAssetType != ProductionMoveType.fighters && stratAssetType != ProductionMoveType.flak &&
                stratAssetType != ProductionMoveType.uboats && stratAssetType != ProductionMoveType.V1 &&
                stratAssetType != ProductionMoveType.V2)
            {
                throw new ArgumentException("Invalid Production Type to create strat warfare purchase move with");
            }
            //2.3 Strategic Warfare Building Limits
            else if(stratAssetType == ProductionMoveType.uboats && numBought > MAX_UBOATSPURCHASABLE)
            {
                throw new ArgumentException("U-boat purchase limit exceeded");
            }
            else if (stratAssetType == ProductionMoveType.V1 && numBought > MAX_V1PURCHASABLE)
            {
                throw new ArgumentException("V1 purchase limit exceeded");
            }
            else if (stratAssetType == ProductionMoveType.V2 && numBought > MAX_V2PURCHASABLE)
            {
                throw new ArgumentException("V2 purchase limit exceeded");
            }
            else if(stratAssetType == ProductionMoveType.bombers)
            {
                switch(country)
                {
                    case MapInfo.CountryID.Germany:
                        if(numBought > MAX_NUM_GERMAN_BOMBER_POINTS)
                            throw new ArgumentException("German bomber purchase limit exceeded");
                        break;
                    case MapInfo.CountryID.GreatBritain:
                        if (numBought > MAX_NUM_BRITISH__BOMBER_POINTS)
                            throw new ArgumentException("British bomber purchase limit exceeded");
                        break;
                    case MapInfo.CountryID.USA:
                        if(numBought > MAX_NUM_US_BOMBER_POINTS)
                            throw new ArgumentException("US bomber purchase limit exceeded");
                        break;
                    default:
                        throw new ArgumentException("Invalid production move");
                }
            }
            return new ProductionMove(gameDate, gamePhase, stratAssetType, country, Block.BlockType.airborne, 0, numBought, MapInfo.RegionID.Albania, 0);
        }

        public static ProductionMove CreateNewGSUMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase, MapInfo.CountryID country, MapInfo.RegionID region)
        {
            return new ProductionMove(gameDate, gamePhase, ProductionMoveType.newGSU, country, Block.BlockType.airborne, 0, 1, region, 0);
        }

        public static ProductionMove CreateSpecialActionUnlimitedReplacementsMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase, MapInfo.CountryID country, MapInfo.RegionID region)
        {
            return new ProductionMove(gameDate, gamePhase, ProductionMoveType.specialActionUnlimitedReplacement, country, Block.BlockType.airborne, 0, 1, region, 0);
        }

        public static ProductionMove CreateSpecialActionMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase, MapInfo.CountryID country)
        {
            return new ProductionMove(gameDate, gamePhase, ProductionMoveType.specialAction, country, Block.BlockType.airborne, 0, 0, MapInfo.RegionID.Albania, 0);
        }

        public static ProductionMove CreateFortificationMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase, MapInfo.CountryID country, MapInfo.RegionID region)
        {
            return new ProductionMove(gameDate, gamePhase, ProductionMoveType.fortification, country, Block.BlockType.airborne, 0, 0, region, 0);
        }

        public static ProductionMove CreateHeavyFortificationMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase, MapInfo.RegionID region)
        {
            return new ProductionMove(gameDate, gamePhase, ProductionMoveType.sovietHeavyFortification, MapInfo.CountryID.USSR, Block.BlockType.airborne, 0, 0, region, 0);
        }

        protected override void ProcessMove(GameState gameState)
        {
            LandRegionState regionState;
            switch(this.MoveType)
            {
                case ProductionMoveType.ASW:
                    gameState.BuildASWLevel();
                    break;
                case ProductionMoveType.blockReplacement:
                    regionState = (LandRegionState)gameState.GetRegionState(this.region);
                    Block block;
                    for (int i = 0; (block = regionState.GetBlockAt(i)) != null; i++)
                    {
                        if(block.CountryOwner == this.Country)
                            if(block.getBlockType() == this.blockType)
                                if(block.MaxStrength == this.producedBlockMaxStrength)
                                    if(block.CurrentStrength == this.previousBlockStrength)
                                    {
                                        block.CurrentStrength++;
                                        break;
                                    }
                    }
                    break;
                case ProductionMoveType.fortification:
                    regionState = (LandRegionState)gameState.GetRegionState(this.region);
                    regionState.FortLevel = LandRegionState.FieldFortificationLevel.fieldfortification;
                    break;
                case ProductionMoveType.sovietHeavyFortification:
                    regionState = (LandRegionState)gameState.GetRegionState(this.region);
                    regionState.FortLevel = LandRegionState.FieldFortificationLevel.sovietheavyfieldfortification;
                    gameState.SovietHeavyFortificationsBuilt++;
                    break;
                case ProductionMoveType.bombers:
                    if (this.Country == MapInfo.CountryID.Germany)
                        gameState.GermanBomberPoints += (uint)this.numBought;
                    else if (this.Country == MapInfo.CountryID.GreatBritain || this.Country == MapInfo.CountryID.USA)
                        gameState.WesternAlliedBomberPoints += (uint)this.numBought;
                    break;
                case ProductionMoveType.fighters:
                    if (this.Country == MapInfo.CountryID.Germany)
                        gameState.GermanFighterPoints += (uint)this.numBought;
                    else if (this.Country == MapInfo.CountryID.GreatBritain || this.Country == MapInfo.CountryID.USA)
                        gameState.WesternAlliedFighterPoints += (uint)this.numBought;
                    break;
                case ProductionMoveType.flak:
                    if (this.Country == MapInfo.CountryID.Germany)
                        gameState.BuildGermanFlakLevel();
                    else if (this.Country == MapInfo.CountryID.GreatBritain)
                        gameState.BuildBritishFlakLevel();
                    break;
                case ProductionMoveType.newBlock:
                    gameState.PlaceBlockFromPoolIntoLandRegion(this.region, this.country, this.blockType, this.producedBlockMaxStrength, 1);
                    break;
                case ProductionMoveType.russianEliteInfantryReinforcement:
                    ForcePool russianForcePool = gameState.GetForcePoolForCountry(MapInfo.CountryID.USSR);
                    russianForcePool.PoolFactoryLock = false;
                    russianForcePool.CreateBlocksInPool(MapInfo.CountryID.USSR, Block.BlockType.eliteInfantry, 4, 1);
                    gameState.PlaceBlockFromPoolIntoLandRegion(this.region, MapInfo.CountryID.USSR, Block.BlockType.eliteInfantry, 4, 4);
                    russianForcePool.PoolFactoryLock = true;
                    break;
                case ProductionMoveType.newfleet:
                    gameState.BuildFleetPoint(this.region,this.country);
                    break;
                case ProductionMoveType.newGSU:
                    gameState.PlaceGSUFromPoolIntoLandRegion(this.region, this.country);
                    break;
                case ProductionMoveType.specialAction:
                    gameState.BuildSpecialAction(this.country);
                    break;
                case ProductionMoveType.specialActionUnlimitedReplacement:
                    gameState.SpendSpecialAction(this.country);
                    break;
                case ProductionMoveType.uboats:
                    gameState.UBOATPoints += (uint)this.numBought;
                    break;
                case ProductionMoveType.V1:
                    gameState.V1ROCKETLevel += (uint)this.numBought;
                    break;
                case ProductionMoveType.V2:
                    gameState.V2ROCKETLevel += (uint)this.numBought;
                    break;
            }
        }

        public void ProcessBlockListModification(List<Block> listToModify, MapInfo.RegionID region)
        {
            if (this.ProductionRegion == region)
            {
                if (this.MoveType == ProductionMove.ProductionMoveType.blockReplacement)
                {
                    foreach(Block blockToModify in listToModify)
                    {
                        if(blockToModify.getBlockType() == this.ProductionBlockType)
                            if(blockToModify.CurrentStrength == this.previousBlockStrength)
                                if(blockToModify.MaxStrength == this.producedBlockMaxStrength)
                                    if(blockToModify.CountryOwner == this.country)
                                    {
                                        if (blockToModify.CurrentStrength < blockToModify.MaxStrength)
                                            blockToModify.CurrentStrength++;
                                        else
                                            throw new InvalidOperationException();
                                        break;
                                    }
                    }
                }
                else if (this.MoveType == ProductionMove.ProductionMoveType.newBlock)
                {
                    Block blockToAdd;
                    switch (this.ProductionBlockType)
                    {
                        case Block.BlockType.militia:
                            blockToAdd = new MilitiaBlock(this.country, this.producedBlockMaxStrength);
                            break;
                        case Block.BlockType.infantry:
                            blockToAdd = new InfantryBlock(this.country, this.producedBlockMaxStrength);
                            break;
                        case Block.BlockType.eliteInfantry:
                            blockToAdd = new EliteInfantryBlock(this.country, this.producedBlockMaxStrength);
                            break;
                        case Block.BlockType.airborne:
                            blockToAdd = new AirborneBlock(this.country, this.producedBlockMaxStrength);
                            break;
                        case Block.BlockType.cavalry:
                            blockToAdd = new CavalryBlock(this.country, this.producedBlockMaxStrength);
                            break;
                        case Block.BlockType.armor:
                            blockToAdd = new ArmorBlock(this.country, this.producedBlockMaxStrength);
                            break;
                        case Block.BlockType.eliteArmor:
                            blockToAdd = new EliteArmorBlock(this.country, this.producedBlockMaxStrength);
                            break;
                        default:
                            throw new InvalidOperationException();
                    }

                    blockToAdd.CurrentStrength = 1;
                    listToModify.Add(blockToAdd);
                }
                else if(this.MoveType == ProductionMoveType.russianEliteInfantryReinforcement)
                {
                    EliteInfantryBlock blockToAdd = new EliteInfantryBlock(MapInfo.CountryID.USSR, 4);
                    listToModify.Add(blockToAdd);
                }
            }
        }

        public static int GetNewUnitProductionCost(PlayingPiece piece, bool cadreBonus)
        {
            if(piece is GroundSupportUnit)
            {
                return GSU_COST;
            }
            else if(piece is Block)
            {
                switch(((Block)piece).getBlockType())
                {
                    case Block.BlockType.infantry:
                        if(cadreBonus)
                            return ProductionMove.INFANTRY_STEP_COST;
                        else
                            return ProductionMove.INFANTRY_STEP_COST * 2;
                    case Block.BlockType.militia:
                        return ProductionMove.MILITIA_STEP_COST;
                    case Block.BlockType.eliteInfantry:
                        if(cadreBonus)
                            return ProductionMove.ELITE_INFANTRY_STEP_COST;
                        else
                            return ProductionMove.ELITE_INFANTRY_STEP_COST * 2;
                    case Block.BlockType.armor:
                        if(cadreBonus)
                            return ProductionMove.ARMOR_STEP_COST;
                        else
                            return ProductionMove.ARMOR_STEP_COST * 2;
                    case Block.BlockType.eliteArmor:
                        if(cadreBonus)
                            return ProductionMove.ELITE_ARMOR_STEP_COST;
                        else
                            return ProductionMove.ELITE_ARMOR_STEP_COST * 2;
                    case Block.BlockType.cavalry:
                        if(cadreBonus)
                            return ProductionMove.CAVALRY_STEP_COST;
                        else
                            return ProductionMove.CAVALRY_STEP_COST * 2;
                    case Block.BlockType.airborne:
                        if (cadreBonus)
                            return ProductionMove.AIRBORNE_STEP_COST;
                        else
                            return ProductionMove.AIRBORNE_STEP_COST * 2;
                }
            }

            return 0;
        }

        public int GetProductionMoveCost()
        {
            int cost = 0;
            switch (type)
            {
                case ProductionMove.ProductionMoveType.blockReplacement:
                    switch (blockType)
                    {
                        case Block.BlockType.airborne:
                            cost = ProductionMove.AIRBORNE_STEP_COST;
                            break;
                        case Block.BlockType.armor:
                            cost = ProductionMove.ARMOR_STEP_COST;
                            break;
                        case Block.BlockType.cavalry:
                            cost = ProductionMove.CAVALRY_STEP_COST;
                            break;
                        case Block.BlockType.eliteArmor:
                            cost = ProductionMove.ELITE_ARMOR_STEP_COST;
                            break;
                        case Block.BlockType.eliteInfantry:
                            cost = ProductionMove.ELITE_INFANTRY_STEP_COST;
                            break;
                        case Block.BlockType.infantry:
                            if (russianEmergencyConscription)
                                cost = 0;
                            else
                                cost = ProductionMove.INFANTRY_STEP_COST;
                            break;
                        case Block.BlockType.militia:
                            cost = ProductionMove.MILITIA_STEP_COST;
                            break;
                    }
                    if (russianBritishProductionPenalty)
                        cost++;
                    break;
                case ProductionMoveType.fortification:
                    cost = FIELD_FORTIFICATION_COST;
                    break;
                case ProductionMoveType.newBlock:
                    switch (blockType)
                    {
                        case Block.BlockType.airborne:
                            if (this.russianCadreBonus)
                                cost = ProductionMove.AIRBORNE_STEP_COST;
                            else
                                cost = ProductionMove.AIRBORNE_STEP_COST * 2;
                            break;
                        case Block.BlockType.armor:
                            if (this.russianCadreBonus)
                                cost = ProductionMove.ARMOR_STEP_COST;
                            else
                                cost = ProductionMove.ARMOR_STEP_COST * 2;
                            break;
                        case Block.BlockType.cavalry:
                            if (this.russianCadreBonus)
                                cost = ProductionMove.CAVALRY_STEP_COST;
                            else
                                cost = ProductionMove.CAVALRY_STEP_COST * 2;
                            break;
                        case Block.BlockType.eliteArmor:
                            if (this.russianCadreBonus)
                                cost = ProductionMove.ELITE_ARMOR_STEP_COST;
                            else
                                cost = ProductionMove.ELITE_ARMOR_STEP_COST * 2;
                            break;
                        case Block.BlockType.eliteInfantry:
                            if (this.russianCadreBonus)
                                cost = ProductionMove.ELITE_INFANTRY_STEP_COST;
                            else
                                cost = ProductionMove.ELITE_INFANTRY_STEP_COST * 2;
                            break;
                        case Block.BlockType.infantry:
                            if (russianEmergencyConscription)
                                cost = 0;
                            else
                            {
                                if (this.russianCadreBonus)
                                    cost = ProductionMove.INFANTRY_STEP_COST;
                                else
                                    cost = ProductionMove.INFANTRY_STEP_COST * 2;
                            }
                            break;
                        case Block.BlockType.militia:
                            cost = ProductionMove.MILITIA_STEP_COST;
                            break;
                    }
                    if (russianBritishProductionPenalty)
                        cost++;
                    break;
                case ProductionMoveType.russianEliteInfantryReinforcement:
                    return 0;
                case ProductionMoveType.newGSU:
                    cost = GSU_COST;
                    break;
                case ProductionMoveType.sovietHeavyFortification:
                    cost = HEAVY_FIELD_FORTIFICATION_COST;
                    break;
            }

            return cost;
        }

        public static int GetBlockCost(Block.BlockType blockType, bool productionPenalty)
        {
            int cost = 0;
            switch (blockType)
            {
                case Block.BlockType.airborne:
                    cost = ProductionMove.AIRBORNE_STEP_COST;
                    break;
                case Block.BlockType.armor:
                    cost = ProductionMove.ARMOR_STEP_COST;
                    break;
                case Block.BlockType.cavalry:
                    cost = ProductionMove.CAVALRY_STEP_COST;
                    break;
                case Block.BlockType.eliteArmor:
                    cost = ProductionMove.ELITE_ARMOR_STEP_COST;
                    break;
                case Block.BlockType.eliteInfantry:
                    cost = ProductionMove.ELITE_INFANTRY_STEP_COST;
                    break;
                case Block.BlockType.infantry:
                    cost = ProductionMove.INFANTRY_STEP_COST;
                    break;
                case Block.BlockType.militia:
                    cost = ProductionMove.MILITIA_STEP_COST;
                    break;
            }

            if (productionPenalty)
                cost++;

            return cost;
        }

        public static int GetBlockCost(Block.BlockType blockType)
        {
            return GetBlockCost(blockType, false);
        }

        public override bool IsLegal(IGameStateInfoProvider gameStateInfoProvider, ref string ruleString)
        {
            return true;
        }

        public override System.Xml.XmlNode Serialise(System.Xml.XmlDocument xml)
        {
            System.Xml.XmlNode nodeToReturn = xml.CreateElement("Move");
            System.Xml.XmlAttribute typeAttr = xml.CreateAttribute("Type");
            System.Xml.XmlAttribute productionTypeAttr = xml.CreateAttribute("productionType");
            System.Xml.XmlAttribute countryAttr = xml.CreateAttribute("country");
            System.Xml.XmlAttribute blockTypeAttr = xml.CreateAttribute("blockType");
            System.Xml.XmlAttribute regionAttr = xml.CreateAttribute("region");
            System.Xml.XmlAttribute producedBlockMaxStrengthAttr = xml.CreateAttribute("producedBlockMaxStrength");
            System.Xml.XmlAttribute previousBlockStrengthAttr = xml.CreateAttribute("previousBlockStrength");
            System.Xml.XmlAttribute numBoughtAttr = xml.CreateAttribute("numBought");
            System.Xml.XmlAttribute russianEmergencyConscriptionAttr = xml.CreateAttribute("russianEmergencyConscription");
            System.Xml.XmlAttribute russianBritishProductionPenaltyAttr = xml.CreateAttribute("russianBritishProductionPenalty");
            System.Xml.XmlAttribute russianCadreBonusAttr = xml.CreateAttribute("russianCadreBonus");

            nodeToReturn.AppendChild(gameTurn.Serialise(xml));
            typeAttr.Value = this.GetType().ToString();
            productionTypeAttr.Value = Enum.GetName(type.GetType(), type);
            countryAttr.Value = Enum.GetName(country.GetType(), country);
            blockTypeAttr.Value = Enum.GetName(blockType.GetType(), blockType);
            regionAttr.Value = Enum.GetName(region.GetType(), region);
            producedBlockMaxStrengthAttr.Value = producedBlockMaxStrength.ToString();
            previousBlockStrengthAttr.Value = previousBlockStrength.ToString();
            numBoughtAttr.Value = numBought.ToString();
            russianEmergencyConscriptionAttr.Value = russianEmergencyConscription.ToString();
            russianBritishProductionPenaltyAttr.Value = russianBritishProductionPenalty.ToString();
            russianCadreBonusAttr.Value = russianCadreBonus.ToString();

            nodeToReturn.Attributes.Append(typeAttr);
            nodeToReturn.Attributes.Append(productionTypeAttr);
            nodeToReturn.Attributes.Append(countryAttr);
            nodeToReturn.Attributes.Append(blockTypeAttr);
            nodeToReturn.Attributes.Append(regionAttr);
            nodeToReturn.Attributes.Append(producedBlockMaxStrengthAttr);
            nodeToReturn.Attributes.Append(previousBlockStrengthAttr);
            nodeToReturn.Attributes.Append(numBoughtAttr);
            nodeToReturn.Attributes.Append(russianEmergencyConscriptionAttr);
            nodeToReturn.Attributes.Append(russianBritishProductionPenaltyAttr);
            nodeToReturn.Attributes.Append(russianCadreBonusAttr);

            return nodeToReturn;
        }

        public new static Move Deserialise(System.Xml.XmlNode node)
        {
            if (node.Attributes["Type"].Value == typeof(ProductionMove).ToString() && node.Name == "Move")
            {
                GameTurn parsedGameTurn = GameTurn.Deserialise(node.SelectSingleNode("GameTurn"));
                ProductionMove productionMoveToReturn = new ProductionMove(parsedGameTurn.CurrentGameDate, parsedGameTurn.CurrentGamePhase, (ProductionMoveType)Enum.Parse(typeof(ProductionMoveType), node.Attributes["productionType"].Value), (MapInfo.CountryID)Enum.Parse(typeof(MapInfo.CountryID), node.Attributes["country"].Value), (Block.BlockType)Enum.Parse(typeof(Block.BlockType), node.Attributes["blockType"].Value), int.Parse(node.Attributes["previousBlockStrength"].Value), int.Parse(node.Attributes["numBought"].Value), (MapInfo.RegionID)Enum.Parse(typeof(MapInfo.RegionID), node.Attributes["region"].Value), uint.Parse(node.Attributes["producedBlockMaxStrength"].Value));
                productionMoveToReturn.russianEmergencyConscription = bool.Parse(node.Attributes["russianEmergencyConscription"].Value);
                productionMoveToReturn.russianCadreBonus = bool.Parse(node.Attributes["russianCadreBonus"].Value);
                productionMoveToReturn.russianBritishProductionPenalty = bool.Parse(node.Attributes["russianBritishProductionPenalty"].Value);
                return productionMoveToReturn;
            }
            else
                throw new InvalidOperationException();
        }

        public override System.Windows.Forms.TreeNode GetMoveTreeNode(System.Windows.Forms.TreeView treeView)
        {
            System.Reflection.Assembly thisExe;
            thisExe = System.Reflection.Assembly.GetExecutingAssembly();
            System.IO.Stream file;

            switch(this.type)
            {
                case ProductionMoveType.ASW:
                    {
                        if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.ASW_IMAGE_KEY))
                        {
                            file = thisExe.GetManifestResourceStream("EuropeEngulfed.NET.Resources.BritishASWLevel.bmp");
                            Bitmap b = (Bitmap)Bitmap.FromStream(file);
                            treeView.ImageList.Images.Add(PlayingPieceGraphics.ASW_IMAGE_KEY, b);
                            file.Dispose();
                        }
                        return new System.Windows.Forms.TreeNode("ASW produced by " + Enum.GetName(this.country.GetType(), this.country), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.ASW_IMAGE_KEY), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.ASW_IMAGE_KEY));
                    }
                case ProductionMoveType.blockReplacement:
                    {
                        {
                            Block block = null;
                            switch (this.blockType)
                            {
                                case Block.BlockType.airborne:
                                    block = new AirborneBlock(this.country, this.producedBlockMaxStrength);
                                    break;
                                case Block.BlockType.armor:
                                    block = new ArmorBlock(this.country, this.producedBlockMaxStrength);
                                    break;
                                case Block.BlockType.cavalry:
                                    block = new CavalryBlock(this.country, this.producedBlockMaxStrength);
                                    break;
                                case Block.BlockType.eliteArmor:
                                    block = new EliteArmorBlock(this.country, this.producedBlockMaxStrength);
                                    break;
                                case Block.BlockType.eliteInfantry:
                                    block = new EliteInfantryBlock(this.country, this.producedBlockMaxStrength);
                                    break;
                                case Block.BlockType.infantry:
                                    block = new InfantryBlock(this.country, this.producedBlockMaxStrength);
                                    break;
                                case Block.BlockType.militia:
                                    block = new MilitiaBlock(this.country, this.producedBlockMaxStrength);
                                    break;
                            }
                            if (!treeView.ImageList.Images.ContainsKey(block.GetTreeViewImageListKey(true)))
                            {
                                Bitmap b = new Bitmap(treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height);
                                Graphics g = Graphics.FromImage(b);
                                PlayingPieceGraphics.PaintBlockFace(g, (Block)block, new Rectangle(0, 0, treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height), true);
                                treeView.ImageList.Images.Add(block.GetTreeViewImageListKey(true), b);
                            }

                            return new System.Windows.Forms.TreeNode("Block Replacement Taken in " + MapInfo.GetRegionName(this.region), treeView.ImageList.Images.IndexOfKey(block.GetTreeViewImageListKey(true)), treeView.ImageList.Images.IndexOfKey(block.GetTreeViewImageListKey(true)));
                        }
                    }
                case ProductionMoveType.bombers:
                    if(this.country == MapInfo.CountryID.Germany)
                    {
                        if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.WALLIED_BOMBER_IMAGE_KEY))
                        {
                            treeView.ImageList.Images.Add(PlayingPieceGraphics.WALLIED_BOMBER_IMAGE_KEY, PlayingPieceGraphics.GetWesternAlliedBomberImage());
                        }
                        return new System.Windows.Forms.TreeNode(this.numBought.ToString() + " bombers produced", treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.WALLIED_BOMBER_IMAGE_KEY), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.WALLIED_BOMBER_IMAGE_KEY));
                    }
                    else
                    {
                        if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.GERMAN_BOMBER_IMAGE_KEY))
                        {
                            treeView.ImageList.Images.Add(PlayingPieceGraphics.GERMAN_BOMBER_IMAGE_KEY, PlayingPieceGraphics.GetGermanBomberImage());
                        }
                        return new System.Windows.Forms.TreeNode(this.numBought.ToString() + " bombers produced", treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.GERMAN_BOMBER_IMAGE_KEY), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.GERMAN_BOMBER_IMAGE_KEY));
                    }
                case ProductionMoveType.fighters:
                    if (this.country == MapInfo.CountryID.Germany)
                    {
                        if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.WALLIED_FIGHTER_IMAGE_KEY))
                        {
                            treeView.ImageList.Images.Add(PlayingPieceGraphics.WALLIED_FIGHTER_IMAGE_KEY, PlayingPieceGraphics.GetWesternAlliedFighterImage());
                        }
                        return new System.Windows.Forms.TreeNode(this.numBought.ToString() + " fighters produced", treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.WALLIED_FIGHTER_IMAGE_KEY), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.WALLIED_FIGHTER_IMAGE_KEY));
                    }
                    else
                    {
                        if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.GERMAN_FIGHTER_IMAGE_KEY))
                        {
                            treeView.ImageList.Images.Add(PlayingPieceGraphics.GERMAN_FIGHTER_IMAGE_KEY, PlayingPieceGraphics.GetGermanFighterImage());
                        }
                        return new System.Windows.Forms.TreeNode(this.numBought.ToString() + " fighters produced", treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.GERMAN_FIGHTER_IMAGE_KEY), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.GERMAN_FIGHTER_IMAGE_KEY));
                    }
                case ProductionMoveType.flak:
                    if (this.country == MapInfo.CountryID.Germany)
                    {
                        if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.WALLIED_FLAK_IMAGE_KEY))
                        {
                            treeView.ImageList.Images.Add(PlayingPieceGraphics.WALLIED_FLAK_IMAGE_KEY, PlayingPieceGraphics.GetWesternAlliedFlakImage());
                        }
                        return new System.Windows.Forms.TreeNode("flak produced", treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.WALLIED_FLAK_IMAGE_KEY), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.WALLIED_FLAK_IMAGE_KEY));
                    }
                    else
                    {
                        if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.GERMAN_FLAK_IMAGE_KEY))
                        {
                            treeView.ImageList.Images.Add(PlayingPieceGraphics.GERMAN_FLAK_IMAGE_KEY, PlayingPieceGraphics.GetGermanFlakImage());
                        }
                        return new System.Windows.Forms.TreeNode("flak produced", treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.GERMAN_FLAK_IMAGE_KEY), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.GERMAN_FLAK_IMAGE_KEY));
                    }
                case ProductionMoveType.fortification:
                    if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.FORTIFICATION_IMAGE_KEY))
                    {
                        Bitmap b = new Bitmap(treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height);
                        Graphics g = Graphics.FromImage(b);
                        PlayingPieceGraphics.PaintFieldFortification(g, new Rectangle(0, 0, treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height));
                        treeView.ImageList.Images.Add(PlayingPieceGraphics.FORTIFICATION_IMAGE_KEY, b);
                    }
                    return new System.Windows.Forms.TreeNode("fortification built in " + MapInfo.GetRegionName(this.region), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.FORTIFICATION_IMAGE_KEY), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.FORTIFICATION_IMAGE_KEY));
                case ProductionMoveType.newBlock:
                    {
                        Block block = null;
                        switch (this.blockType)
                        {
                            case Block.BlockType.airborne:
                                block = new AirborneBlock(this.country, this.producedBlockMaxStrength);
                                break;
                            case Block.BlockType.armor:
                                block = new ArmorBlock(this.country, this.producedBlockMaxStrength);
                                break;
                            case Block.BlockType.cavalry:
                                block = new CavalryBlock(this.country, this.producedBlockMaxStrength);
                                break;
                            case Block.BlockType.eliteArmor:
                                block = new EliteArmorBlock(this.country, this.producedBlockMaxStrength);
                                break;
                            case Block.BlockType.eliteInfantry:
                                block = new EliteInfantryBlock(this.country, this.producedBlockMaxStrength);
                                break;
                            case Block.BlockType.infantry:
                                block = new InfantryBlock(this.country, this.producedBlockMaxStrength);
                                break;
                            case Block.BlockType.militia:
                                block = new MilitiaBlock(this.country, this.producedBlockMaxStrength);
                                break;
                        }
                        if (!treeView.ImageList.Images.ContainsKey(block.GetTreeViewImageListKey(true)))
                        {
                            Bitmap b = new Bitmap(treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height);
                            Graphics g = Graphics.FromImage(b);
                            PlayingPieceGraphics.PaintBlockFace(g, (Block)block, new Rectangle(0, 0, treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height), true);
                            treeView.ImageList.Images.Add(block.GetTreeViewImageListKey(true), b);
                        }
                        return new System.Windows.Forms.TreeNode("New block produced in " + MapInfo.GetRegionName(this.region), treeView.ImageList.Images.IndexOfKey(block.GetTreeViewImageListKey(true)), treeView.ImageList.Images.IndexOfKey(block.GetTreeViewImageListKey(true)));
                    }
                case ProductionMoveType.newfleet:
                    FleetPoint fleet = new FleetPoint(this.country);
                    if (!treeView.ImageList.Images.ContainsKey(fleet.GetTreeViewImageListKey(true)))
                    {
                        Bitmap b = new Bitmap(treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height);
                        Graphics g = Graphics.FromImage(b);
                        PlayingPieceGraphics.PaintFleetPointFace(g, fleet, new Rectangle(0, 0, treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height));
                        treeView.ImageList.Images.Add(fleet.GetTreeViewImageListKey(true), b);
                    }
                    return new System.Windows.Forms.TreeNode("New fleet produced in " + MapInfo.GetRegionName(this.region), treeView.ImageList.Images.IndexOfKey(fleet.GetTreeViewImageListKey(true)), treeView.ImageList.Images.IndexOfKey(fleet.GetTreeViewImageListKey(true)));
                case ProductionMoveType.newGSU:
                    GroundSupportUnit GSU = new GroundSupportUnit(this.country);
                    if (!treeView.ImageList.Images.ContainsKey(GSU.GetTreeViewImageListKey(true)))
                    {
                        Bitmap b = new Bitmap(treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height);
                        Graphics g = Graphics.FromImage(b);
                        PlayingPieceGraphics.PaintGSUFace(g, GSU, new Rectangle(0, 0, treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height), false);
                        treeView.ImageList.Images.Add(GSU.GetTreeViewImageListKey(true), b);
                    }
                    return new System.Windows.Forms.TreeNode("new Ground support unit built in " + MapInfo.GetRegionName(this.region), treeView.ImageList.Images.IndexOfKey(GSU.GetTreeViewImageListKey(true)), treeView.ImageList.Images.IndexOfKey(GSU.GetTreeViewImageListKey(true)));
                case ProductionMoveType.russianEliteInfantryReinforcement:
                    EliteInfantryBlock eliteRussianInfantryBlock = new EliteInfantryBlock(MapInfo.CountryID.USSR, 4);
                    if (!treeView.ImageList.Images.ContainsKey(eliteRussianInfantryBlock.GetTreeViewImageListKey(false)))
                    {
                        Bitmap b = new Bitmap(treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height);
                        Graphics g = Graphics.FromImage(b);
                        PlayingPieceGraphics.PaintBlockFace(g, eliteRussianInfantryBlock, new Rectangle(0, 0, treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height), false);
                        treeView.ImageList.Images.Add(eliteRussianInfantryBlock.GetTreeViewImageListKey(false), b);
                    }
                    return new System.Windows.Forms.TreeNode("Russian Elite Reinforcement arrived in " + MapInfo.GetRegionName(this.region), treeView.ImageList.Images.IndexOfKey(eliteRussianInfantryBlock.GetTreeViewImageListKey(false)), treeView.ImageList.Images.IndexOfKey(eliteRussianInfantryBlock.GetTreeViewImageListKey(false)));
                case ProductionMoveType.sovietHeavyFortification:
                    if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.HEAVYFORTIFICATION_IMAGE_KEY))
                    {
                        Bitmap b = new Bitmap(treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height);
                        Graphics g = Graphics.FromImage(b);
                        PlayingPieceGraphics.PaintHeavyFieldFortification(g, new Rectangle(0, 0, treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height));
                        treeView.ImageList.Images.Add(PlayingPieceGraphics.HEAVYFORTIFICATION_IMAGE_KEY, b);
                    }
                    return new System.Windows.Forms.TreeNode("Soviet heavy fortification built in " + MapInfo.GetRegionName(this.region), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.HEAVYFORTIFICATION_IMAGE_KEY), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.HEAVYFORTIFICATION_IMAGE_KEY));
                case ProductionMoveType.specialAction:
                    if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.GetTreeViewImageListKeyForSpecialAction(this.country)))
                    {
                        Bitmap b = new Bitmap(treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height);
                        Graphics g = Graphics.FromImage(b);
                        PlayingPieceGraphics.PaintSpecialActionsFace(g, country, new Rectangle(0, 0, treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height));
                        treeView.ImageList.Images.Add(PlayingPieceGraphics.GetTreeViewImageListKeyForSpecialAction(this.country), b);
                    }
                    return new System.Windows.Forms.TreeNode("Special Action purchased by " + Enum.GetName(this.country.GetType(), this.country), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.GetTreeViewImageListKeyForSpecialAction(this.country)), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.GetTreeViewImageListKeyForSpecialAction(this.country)));
                case ProductionMoveType.specialActionUnlimitedReplacement:
                    if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.GetTreeViewImageListKeyForSpecialAction(this.country)))
                    {
                        Bitmap b = new Bitmap(treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height);
                        Graphics g = Graphics.FromImage(b);
                        PlayingPieceGraphics.PaintSpecialActionsFace(g, country, new Rectangle(0, 0, treeView.ImageList.ImageSize.Width, treeView.ImageList.ImageSize.Height));
                        treeView.ImageList.Images.Add(PlayingPieceGraphics.GetTreeViewImageListKeyForSpecialAction(this.country), b);
                    }
                    return new System.Windows.Forms.TreeNode("Special Action spent on unlimited replacements by " + Enum.GetName(this.country.GetType(), this.country) + " in " + MapInfo.GetRegionName(this.region), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.GetTreeViewImageListKeyForSpecialAction(this.country)), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.GetTreeViewImageListKeyForSpecialAction(this.country)));
                case ProductionMoveType.uboats:
                    if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.UBOAT_IMAGE_KEY))
                    {
                        file = thisExe.GetManifestResourceStream("EuropeEngulfed.NET.Resources.GermanUBoatPoints.bmp");
                        Bitmap b = (Bitmap)Bitmap.FromStream(file);
                        treeView.ImageList.Images.Add(PlayingPieceGraphics.UBOAT_IMAGE_KEY, b);
                        file.Dispose();
                    }
                    return new System.Windows.Forms.TreeNode(this.numBought.ToString() + " U-Boats produced", treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.UBOAT_IMAGE_KEY), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.UBOAT_IMAGE_KEY));
                case ProductionMoveType.V1:
                    if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.V1_IMAGE_KEY))
                    {
                        file = thisExe.GetManifestResourceStream("EuropeEngulfed.NET.Resources.GermanV1Points.bmp");
                        Bitmap b = (Bitmap)Bitmap.FromStream(file);
                        treeView.ImageList.Images.Add(PlayingPieceGraphics.V1_IMAGE_KEY, b);
                        file.Dispose();
                    }
                    return new System.Windows.Forms.TreeNode(this.numBought.ToString() + " V1s produced", treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.V1_IMAGE_KEY), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.V1_IMAGE_KEY));
                case ProductionMoveType.V2:
                    if (!treeView.ImageList.Images.ContainsKey(PlayingPieceGraphics.V2_IMAGE_KEY))
                    {
                        file = thisExe.GetManifestResourceStream("EuropeEngulfed.NET.Resources.GermanV2Points.bmp");
                        Bitmap b = (Bitmap)Bitmap.FromStream(file);
                        treeView.ImageList.Images.Add(PlayingPieceGraphics.V2_IMAGE_KEY, b);
                        file.Dispose();
                    }
                    return new System.Windows.Forms.TreeNode(this.numBought.ToString() + " V2s produced", treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.V2_IMAGE_KEY), treeView.ImageList.Images.IndexOfKey(PlayingPieceGraphics.V2_IMAGE_KEY));
                default:
                    throw new NotImplementedException();
            }
        }

        public override string GetStringForNetworkMessage()
        {
            switch(type)
            {
                case ProductionMoveType.ASW:
                    return Enum.GetName(typeof(MapInfo.CountryID), this.country) + " purchased ASW";
                case ProductionMoveType.blockReplacement:
                    return MapInfo.GetCountryAdjective(this.country) + " block replacement received in " + Enum.GetName(typeof(MapInfo.RegionID), this.region);
                case ProductionMoveType.bombers:
                    return this.numBought.ToString() + " bombers bought by " + Enum.GetName(typeof(MapInfo.CountryID), this.country);
                case ProductionMoveType.fighters:
                    return this.numBought.ToString() + " fighters bought by " + Enum.GetName(typeof(MapInfo.CountryID), this.country);
                case ProductionMoveType.flak:
                    return Enum.GetName(typeof(MapInfo.CountryID), this.country) + " purchased Flak";
                case ProductionMoveType.fortification:
                    return Enum.GetName(typeof(MapInfo.CountryID), this.country) + " purchased fortification in " + Enum.GetName(typeof(MapInfo.RegionID), this.region);
                case ProductionMoveType.newBlock:
                    return MapInfo.GetCountryAdjective(this.country) + " new block " + ((this.blockType == Block.BlockType.eliteInfantry || this.blockType == Block.BlockType.eliteArmor) ? "(Elite)" : "") + "built in " + Enum.GetName(typeof(MapInfo.RegionID), this.region);
                case ProductionMoveType.newfleet:
                    return "New fleet purchased in " + Enum.GetName(typeof(MapInfo.RegionID), this.region);
                case ProductionMoveType.newGSU:
                    return MapInfo.GetCountryAdjective(this.country) + " new GSU built in " + Enum.GetName(typeof(MapInfo.RegionID), this.region);
                case ProductionMoveType.russianEliteInfantryReinforcement:
                    return "Russian Elite Reinforcement placed in " + Enum.GetName(typeof(MapInfo.RegionID), this.region);
                case ProductionMoveType.sovietHeavyFortification:
                    return "Soviet Heavy Fortification built in " + Enum.GetName(typeof(MapInfo.RegionID), this.region);
                case ProductionMoveType.specialAction:
                    return MapInfo.GetCountryAdjective(this.country) + " Special Action Built";
                case ProductionMoveType.specialActionUnlimitedReplacement:
                    return MapInfo.GetCountryAdjective(this.country) + " Special Action For Unlimited Reinforcements Spent in " + Enum.GetName(typeof(MapInfo.RegionID), this.region);
                case ProductionMoveType.uboats:
                    return this.numBought.ToString() + " U-Boats bought";
                case ProductionMoveType.V1:
                    return this.numBought.ToString() + " V1s bought";
                case ProductionMoveType.V2:
                    return this.numBought.ToString() + " V2s bought";
                default:
                    return "";
            }
        }
    }
}
